package com.itsitio.dbimporter.helper;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import au.com.bytecode.opencsv.CSVReader;

import com.itsitio.dbimporter.dto.FilaDTO;
import com.itsitio.dbimporter.dto.TablaDTO;
import com.itsitio.dbimporter.modelo.metadata.MetadataCampo;
import com.itsitio.dbimporter.modelo.metadata.MetadataEntidad;
import com.itsitio.dbimporter.modelo.referencia.TipoArchivo;
import com.itsitio.dbimporter.servicio.DbInsertSrv;

@Component
public class DataLoaderManager {
	
	@Autowired
	DbInsertSrv insertSrv;


	/**
	 * Valida los datos del archivo y devuelve un tablaDTO 
	 * con cada fila validada representada por un filaDTO.
	 * @param entity
	 * @param csv
	 * @param file
	 * @return
	 */
	public TablaDTO validarDatosArchivo(MetadataEntidad entity, TipoArchivo csv,
			File file) {
		
			TablaDTO tablaValidada =  new TablaDTO();
			
			List<FilaDTO> filas = new ArrayList<FilaDTO>();
		
			FilaDTO filaValidada = null;
			
			CSVReader reader = null;
			
			List<String[]> lineas = null;
		
		try {
			
			reader = new CSVReader(new FileReader(file),';');
			
			lineas = reader.readAll();
			
			int cant = 0;
			
			for (String[] lineaArray : lineas) {
				
				if(cant != 0){
					
						filaValidada = this.validarDatosFila(entity.getCampos(), lineaArray);
						
						filas.add(filaValidada);
						
					}
				
				cant++;
					
			}
			
			tablaValidada.setFilas(filas);
			
			List<String> titulos =	(List<String>) CollectionUtils.collect(entity.getCampos(), new Transformer() {
				@Override		
				public Object transform(Object arg0) {
							return ((MetadataCampo) arg0).getNombre();
						}
					});
					
			tablaValidada.setTitulos(titulos);		
				
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return tablaValidada;
		
	}

	/**
	 * valida cada fila y devuelve un filaDTO que representa la fila validada.
	 * @param list
	 * @param lineaArray
	 * @return
	 */
	private FilaDTO validarDatosFila(List<MetadataCampo> metadataList,
			String[] lineaArray) {
		
		FilaDTO filaDTO = new FilaDTO();
		
		List<String> valores =  Arrays.asList(lineaArray);
		
		boolean valido = true;
		
		valido = valido && validarCantidadCampos(metadataList.size(), lineaArray.length);
		
		if(valido){
		
			for (MetadataCampo metadataCampo : metadataList) {
				
				valido = valido && this.validarTipoFormatoDato(metadataCampo, lineaArray[metadataCampo.getIndexArchivo()]);
				//aqui se deberia validar con drools
				
			}
		}	
		
		filaDTO.setError(!valido);
		
		filaDTO.setValores(valores);
		
		return filaDTO;
	}

	/**
	 * @param metadataCampo
	 * @param valorCampo
	 * @return
	 */
	private boolean validarTipoFormatoDato(MetadataCampo metadataCampo,
			String valorCampo) {
		
			
			try {
				switch (metadataCampo.getTipoDato()) {
				
				case INTEGER:
					Integer.parseInt(valorCampo);
					break;
					
				case STRING:
					break;

				case DATE:
					Date.valueOf(valorCampo);
					break;
					
				default:
					break;
					
				}
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
			
		
		return true;
		
	}

	/**
	 * @param size
	 * @param length
	 * @return
	 */
	private boolean validarCantidadCampos(int size, int length) {
		return size == length;
	}

	/**
	 * @param entity
	 * @param csv
	 * @param file
	 */
	public void cargarDatosEnBD(MetadataEntidad entity, TipoArchivo csv,
			File file) {

		try {
			CSVReader reader = new CSVReader(new FileReader(file),';');
			List<String[]> lineas = reader.readAll();
			int cant = 0;
			
			for (String[] lineaArray : lineas) {
				if(cant != 0){
					Object[] parametros = new Object[lineaArray.length];
					for (MetadataCampo campo : entity.getCampos()) {
						parametros[campo.getIndexInsert()] = lineaArray[campo.getIndexArchivo()];
					}
					/* codigo, mes, pais, codfab, cantidad */
					insertSrv.ejecutarInsert(entity.getInsertSQL(), parametros);
				}	
				cant++;
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param entity
	 * @param datosValidados
	 * @return
	 */
	public TablaDTO insertarDatosArchivo(MetadataEntidad entity,
			TablaDTO datosValidados) {
		TablaDTO datosInsertados = new TablaDTO();
		datosInsertados.setTitulos(datosValidados.getTitulos());
		List<FilaDTO> filas = new ArrayList<FilaDTO>();
		Object[] parametros = null;
		
		for (FilaDTO fila : datosValidados.getFilas()) {
			
			if(!fila.isError()){
				
				filas.add(fila);
				
				parametros = new Object[fila.getValores().size()];
				
				for (MetadataCampo campo : entity.getCampos()) {
					
					parametros[campo.getIndexInsert()] = fila.getValores().get(campo.getIndexArchivo());
					
				}
				
				try {
					insertSrv.ejecutarInsert(entity.getInsertSQL(), parametros);
				} catch (Exception e) {
					fila.setError(true);
				}
				
			}	
		}
		
		datosInsertados.setFilas(filas);
		
		return datosInsertados;
	}

	 
}
